bitkeeper revision 1.1159.1.565 (420b7bafUdB4uOmG-Qm1AYMify0jrQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 10 Feb 2005 15:20:15 +0000 (15:20 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Thu, 10 Feb 2005 15:20:15 +0000 (15:20 +0000)
p2m and m2p tables are now 4 bytes per entry always, even on x86/64.
Fixed mapping of m2p table into kernel space on x86/64.
Signed-off-by: keir.fraser@cl.cam.ac.uk
15 files changed:
linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c
linux-2.4.29-xen-sparse/include/asm-xen/page.h
linux-2.4.29-xen-sparse/include/asm-xen/pgtable-2level.h
linux-2.6.10-xen-sparse/arch/xen/i386/kernel/setup.c
linux-2.6.10-xen-sparse/arch/xen/kernel/reboot.c
linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/page.h
linux-2.6.10-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h
xen/arch/x86/domain.c
xen/arch/x86/x86_32/domain_build.c
xen/arch/x86/x86_64/domain_build.c
xen/arch/x86/x86_64/mm.c
xen/include/asm-x86/mm.h
xen/include/asm-x86/shadow.h
xen/include/public/arch-x86_32.h
xen/include/public/arch-x86_64.h

index fcaf2a89de24eea30738204e700bfb9ab5f474b4..063b4427df91508d35d84e0a059ca3ed8ddf1ec7 100644 (file)
@@ -60,7 +60,7 @@ static int errno;
  */
 shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
 
-unsigned long *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
+unsigned int *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
 
 DEFINE_PER_CPU(multicall_entry_t, multicall_list[8]);
 DEFINE_PER_CPU(int, nr_multicall_ents);
@@ -327,7 +327,7 @@ void __init setup_arch(char **cmdline_p)
     }
 #endif
 
-    phys_to_machine_mapping = (unsigned long *)xen_start_info.mfn_list;
+    phys_to_machine_mapping = (unsigned int *)xen_start_info.mfn_list;
     cur_pgd = init_mm.pgd = (pgd_t *)xen_start_info.pt_base;
 
     start_pfn = (__pa(xen_start_info.pt_base) >> PAGE_SHIFT) + 
@@ -382,7 +382,7 @@ void __init setup_arch(char **cmdline_p)
     {
         phys_to_machine_mapping = alloc_bootmem_low_pages(
             max_pfn * sizeof(unsigned long));
-        memset(phys_to_machine_mapping, ~0, max_pfn * sizeof(unsigned long));
+        memset(phys_to_machine_mapping, ~0, max_pfn * sizeof(unsigned int));
         memcpy(phys_to_machine_mapping,
                (unsigned long *)xen_start_info.mfn_list,
                xen_start_info.nr_pages * sizeof(unsigned long));
index 546cb65b2213f76d0fb3481137bb550baade5a49..78863c36daa7ec9cbbec54be9b3b7e10d07d76e8 100644 (file)
@@ -43,9 +43,9 @@
 #define copy_user_page(to, from, vaddr)        copy_page(to, from)
 
 /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
-extern unsigned long *phys_to_machine_mapping;
-#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
-#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
+extern unsigned int *phys_to_machine_mapping;
+#define pfn_to_mfn(_pfn) ((unsigned long)(phys_to_machine_mapping[(_pfn)]))
+#define mfn_to_pfn(_mfn) ((unsigned long)(machine_to_phys_mapping[(_mfn)]))
 static inline unsigned long phys_to_machine(unsigned long phys)
 {
     unsigned long machine = pfn_to_mfn(phys >> PAGE_SHIFT);
index 9ddd30bf73dcb42a52e693dd54bd02cab753cdfe..fb6644aedf1386b0cf6db942276dcbc0829ba882 100644 (file)
@@ -69,7 +69,7 @@ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
  *      require. In all the cases we care about, the high bit gets shifted out
  *      (e.g., phys_to_machine()) so behaviour there is correct.
  */
-#define INVALID_P2M_ENTRY (~0UL)
+#define INVALID_P2M_ENTRY (~0U)
 #define FOREIGN_FRAME(_m) ((_m) | (1UL<<((sizeof(unsigned long)*8)-1)))
 #define pte_page(_pte)                                        \
 ({                                                            \
index cc3ba24b97041e9668e5dfa89076c018dffd4ef8..5285439c364b153a8d72e27fa434b123bdeba439 100644 (file)
@@ -345,7 +345,7 @@ static void __init probe_roms(void)
 shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
 EXPORT_SYMBOL(HYPERVISOR_shared_info);
 
-unsigned long *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
+unsigned int *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
 EXPORT_SYMBOL(phys_to_machine_mapping);
 
 DEFINE_PER_CPU(multicall_entry_t, multicall_list[8]);
@@ -1142,7 +1142,7 @@ static unsigned long __init setup_memory(void)
        }
 #endif
 
-       phys_to_machine_mapping = (unsigned long *)xen_start_info.mfn_list;
+       phys_to_machine_mapping = (unsigned int *)xen_start_info.mfn_list;
 
        return max_low_pfn;
 }
index 07aae9d0c60d2fb52f52db75ed2c95203dbdd5e4..f69db851a4fc77b310c6df7ef01f550fc7110e66 100644 (file)
@@ -80,7 +80,7 @@ static void __do_suspend(void)
     extern void time_suspend(void);
     extern void time_resume(void);
     extern unsigned long max_pfn;
-    extern unsigned long *pfn_to_mfn_frame_list;
+    extern unsigned int *pfn_to_mfn_frame_list;
 
     suspend_record = (suspend_record_t *)__get_free_page(GFP_KERNEL);
     if ( suspend_record == NULL )
index da282bd498093fbe88772fbd341b158e7436a78b..6215a5b01868288a1e4290b786776d8be17b553a 100644 (file)
@@ -55,9 +55,9 @@
 #define copy_user_page(to, from, vaddr, pg)    copy_page(to, from)
 
 /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
-extern unsigned long *phys_to_machine_mapping;
-#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
-#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
+extern unsigned int *phys_to_machine_mapping;
+#define pfn_to_mfn(_pfn) ((unsigned long)(phys_to_machine_mapping[(_pfn)]))
+#define mfn_to_pfn(_mfn) ((unsigned long)(machine_to_phys_mapping[(_mfn)]))
 static inline unsigned long phys_to_machine(unsigned long phys)
 {
        unsigned long machine = pfn_to_mfn(phys >> PAGE_SHIFT);
index c7db3fee598885d4b031adee23c27ea4615e0c1c..3abd3ce14a56a5417b1092e4caf9a32802cb39b5 100644 (file)
@@ -92,7 +92,7 @@ static inline pte_t ptep_get_and_clear(pte_t *xp)
  *      require. In all the cases we care about, the high bit gets shifted out
  *      (e.g., phys_to_machine()) so behaviour there is correct.
  */
-#define INVALID_P2M_ENTRY (~0UL)
+#define INVALID_P2M_ENTRY (~0U)
 #define FOREIGN_FRAME(_m) ((_m) | (1UL<<((sizeof(unsigned long)*8)-1)))
 #define pte_pfn(_pte)                                                  \
 ({                                                                     \
index 294ed178c1018879711a461f0d7dd4c501ecde50..2ff1455820307c36719d737c12226f59ceac6424 100644 (file)
@@ -271,12 +271,12 @@ void arch_do_createdomain(struct exec_domain *ed)
         ed->vcpu_info = &d->shared_info->vcpu_data[ed->eid];
         SHARE_PFN_WITH_DOMAIN(virt_to_page(d->shared_info), d);
         machine_to_phys_mapping[virt_to_phys(d->shared_info) >> 
-                               PAGE_SHIFT] = INVALID_P2M_ENTRY;
+                               PAGE_SHIFT] = INVALID_M2P_ENTRY;
 
         d->arch.mm_perdomain_pt = (l1_pgentry_t *)alloc_xenheap_page();
         memset(d->arch.mm_perdomain_pt, 0, PAGE_SIZE);
         machine_to_phys_mapping[virt_to_phys(d->arch.mm_perdomain_pt) >> 
-                               PAGE_SHIFT] = INVALID_P2M_ENTRY;
+                               PAGE_SHIFT] = INVALID_M2P_ENTRY;
         ed->arch.perdomain_ptes = d->arch.mm_perdomain_pt;
 
 #ifdef __x86_64__
@@ -687,7 +687,8 @@ long do_switch_to_user(void)
     struct switch_to_user  stu;
     struct exec_domain    *ed = current;
 
-    if ( unlikely(copy_from_user(&stu, (void *)regs->rsp, sizeof(stu))) )
+    if ( unlikely(copy_from_user(&stu, (void *)regs->rsp, sizeof(stu))) ||
+         unlikely(pagetable_val(ed->arch.pagetable_user) == 0) )
         return -EFAULT;
 
     ed->arch.flags &= ~TF_kernel_mode;
index b6f8624d06e9438e38739b9f0aa88523da17e985..2c11f71668507d48356e8e7886380894e9e93b52 100644 (file)
@@ -116,7 +116,7 @@ int construct_dom0(struct domain *d,
     vinitrd_start    = round_pgup(dsi.v_kernend);
     vinitrd_end      = vinitrd_start + initrd_len;
     vphysmap_start   = round_pgup(vinitrd_end);
-    vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
+    vphysmap_end     = vphysmap_start + (nr_pages * sizeof(u32));
     vpt_start        = round_pgup(vphysmap_end);
     for ( nr_pt_pages = 2; ; nr_pt_pages++ )
     {
@@ -337,7 +337,7 @@ int construct_dom0(struct domain *d,
         if ( pfn > REVERSE_START )
             mfn = (alloc_end>>PAGE_SHIFT) - (pfn - REVERSE_START);
 #endif
-        ((unsigned long *)vphysmap_start)[pfn] = mfn;
+        ((u32 *)vphysmap_start)[pfn] = mfn;
         machine_to_phys_mapping[mfn] = pfn;
     }
 
index f84a3e0f9c67276b4a1dfead52cdf3e3c9f19650..bd82b4ef7cfe4cb71c2a01f0b3d4ca33ce0b674f 100644 (file)
@@ -119,7 +119,7 @@ int construct_dom0(struct domain *d,
     vinitrd_start    = round_pgup(dsi.v_kernend);
     vinitrd_end      = vinitrd_start + initrd_len;
     vphysmap_start   = round_pgup(vinitrd_end);
-    vphysmap_end     = vphysmap_start + (nr_pages * sizeof(unsigned long));
+    vphysmap_end     = vphysmap_start + (nr_pages * sizeof(u32));
     vpt_start        = round_pgup(vphysmap_end);
     for ( nr_pt_pages = 2; ; nr_pt_pages++ )
     {
@@ -358,7 +358,7 @@ int construct_dom0(struct domain *d,
         if ( pfn > REVERSE_START )
             mfn = (alloc_end>>PAGE_SHIFT) - (pfn - REVERSE_START);
 #endif
-        ((unsigned long *)vphysmap_start)[pfn] = mfn;
+        ((u32 *)vphysmap_start)[pfn] = mfn;
         machine_to_phys_mapping[mfn] = pfn;
     }
 
index f69d06a1cfdf422ab3a3c7d2bb173d43968cc9c5..5bced9a509e30ff21145c92979af2898f0257896 100644 (file)
@@ -115,8 +115,8 @@ void __set_fixmap(
 
 void __init paging_init(void)
 {
-    void *newpt;
     unsigned long i, p, max;
+    l3_pgentry_t *l3rw, *l3ro;
 
     /* Map all of physical memory. */
     max = ((max_page + L1_PAGETABLE_ENTRIES - 1) & 
@@ -134,25 +134,32 @@ void __init paging_init(void)
         if ( p == 0 )
             panic("Not enough memory for m2p table\n");
         map_pages(idle_pg_table, RDWR_MPT_VIRT_START + i*8, p, 
-                  1UL << L2_PAGETABLE_SHIFT, PAGE_HYPERVISOR);
+                  1UL << L2_PAGETABLE_SHIFT, PAGE_HYPERVISOR | _PAGE_USER);
         memset((void *)(RDWR_MPT_VIRT_START + i*8), 0x55,
                1UL << L2_PAGETABLE_SHIFT);
     }
 
+    /*
+     * Above we mapped the M2P table as user-accessible and read-writable.
+     * Fix security by denying user access at the top level of the page table.
+     */
+    idle_pg_table[l4_table_offset(RDWR_MPT_VIRT_START)] =
+        mk_l4_pgentry(l4_pgentry_val(
+            idle_pg_table[l4_table_offset(RDWR_MPT_VIRT_START)]) & 
+                      ~_PAGE_USER);
+
     /* Create read-only mapping of MPT for guest-OS use. */
-    newpt = (void *)alloc_xenheap_page();
-    clear_page(newpt);
+    l3ro = (l3_pgentry_t *)alloc_xenheap_page();
+    clear_page(l3ro);
     idle_pg_table[l4_table_offset(RO_MPT_VIRT_START)] =
-        mk_l4_pgentry((__pa(newpt) | __PAGE_HYPERVISOR | _PAGE_USER) &
+        mk_l4_pgentry((__pa(l3ro) | __PAGE_HYPERVISOR | _PAGE_USER) &
                       ~_PAGE_RW);
     /* Copy the L3 mappings from the RDWR_MPT area. */
-    p  = l4_pgentry_val(idle_pg_table[l4_table_offset(RDWR_MPT_VIRT_START)]);
-    p &= PAGE_MASK;
-    p += l3_table_offset(RDWR_MPT_VIRT_START) * sizeof(l3_pgentry_t);
-    newpt = (void *)((unsigned long)newpt +
-                     (l3_table_offset(RO_MPT_VIRT_START) *
-                      sizeof(l3_pgentry_t)));
-    memcpy(newpt, __va(p),
+    l3rw = l4_pgentry_to_l3(
+        idle_pg_table[l4_table_offset(RDWR_MPT_VIRT_START)]);
+    l3rw += l3_table_offset(RDWR_MPT_VIRT_START);
+    l3ro += l3_table_offset(RO_MPT_VIRT_START);
+    memcpy(l3ro, l3rw,
            (RDWR_MPT_VIRT_END - RDWR_MPT_VIRT_START) >> L3_PAGETABLE_SHIFT);
 
     /* Set up linear page table mapping. */
index 4d36b6c25b1665ea0018e5c8bf89ccf865ff9fe9..1d0cf33c24e00ce0552265cd21f55e9263b27f1e 100644 (file)
@@ -128,8 +128,6 @@ static inline u32 pickle_domptr(struct domain *domain)
         spin_unlock(&(_dom)->page_alloc_lock);                              \
     } while ( 0 )
 
-#define INVALID_P2M_ENTRY (~0UL)
-
 extern struct pfn_info *frame_table;
 extern unsigned long frame_table_size;
 extern unsigned long max_page;
@@ -231,15 +229,16 @@ void synchronise_pagetables(unsigned long cpu_mask);
  * contiguous (or near contiguous) physical memory.
  */
 #undef  machine_to_phys_mapping
+#define machine_to_phys_mapping ((u32 *)RDWR_MPT_VIRT_START)
+#define INVALID_M2P_ENTRY        (~0U)
+#define IS_INVALID_M2P_ENTRY(_e) (!!((_e) & (1U<<31)))
 
 /*
  * The phys_to_machine_mapping is the reversed mapping of MPT for full
  * virtualization.
  */
-#undef  phys_to_machine_mapping
-
-#define machine_to_phys_mapping ((unsigned long *)RDWR_MPT_VIRT_START)
 #define __phys_to_machine_mapping ((unsigned long *)PERDOMAIN_VIRT_START)
+
 /* Returns the machine physical */
 static inline unsigned long phys_to_machine_mapping(unsigned long pfn) 
 {
index 15858d5901521622cd394e07ddea8c60573699b3..62e30cd328a3bffb2ce78b8144a69f4d82a0ef82 100644 (file)
@@ -181,7 +181,7 @@ static inline int __mark_dirty(struct domain *d, unsigned int mfn)
      * domain's pseudo-physical memory map (e.g., the shared info frame).
      * Nothing to do here...
      */
-    if ( unlikely(pfn & 0x80000000UL) )
+    if ( unlikely(IS_INVALID_M2P_ENTRY(pfn)) )
         return rc;
 
     if ( likely(pfn < d->arch.shadow_dirty_bitmap_size) )
index 524138fd09fc020cd63408665cdfbf9e743a9557..65abc26efb5b764d629ef10ec858963f98088b1b 100644 (file)
@@ -71,7 +71,7 @@
  */
 #define HYPERVISOR_VIRT_START (0xFC000000UL)
 #ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
 #endif
 
 #ifndef __ASSEMBLY__
index 3f14c3a8095a43be8165056e480f60c4eeacc0dd..aba053181ed0e2ff46aa34d97004d8911c570e12 100644 (file)
@@ -81,7 +81,7 @@
 
 /* The machine->physical mapping table starts at this address, read-only. */
 #ifndef machine_to_phys_mapping
-#define machine_to_phys_mapping ((unsigned long *)HYPERVISOR_VIRT_START)
+#define machine_to_phys_mapping ((u32 *)HYPERVISOR_VIRT_START)
 #endif
 
 /*